
#include "MTypes.h"
#include "MList.h"
#include <sstream>

#include "Markup.h"
#include "MException.h"
BEGIN_MARIONETTE
using namespace std;
MTypes_Imp::MTypes_Imp(void)
{
	CreateInnerTypes();
}


MTypes_Imp::~MTypes_Imp(void)
{
	ClearAll();
}
//MTypes_Imp* MTypes_Imp::Instance(){
//	static MTypes_Imp* pMTypes = new MTypes_Imp();
//	return pMTypes;
//}

MType* MTypes_Imp::operator[]( MString typeName )
{
	return GetTypeByName(typeName);
}

MType* MTypes_Imp::GetTypeByName( MString typeName )
{
	TypeContainer_Type::iterator iter = m_TypesContainer.find(typeName);
	if(iter != m_TypesContainer.end())
		return iter->second;
	return NULL;
}

void MTypes_Imp::AddType( MType* pType )
{
	m_TypesContainer.insert(make_pair(pType->Name(),pType));
	MType* pPointerType = new MPointer(pType);
	m_TypesContainer.insert(make_pair(pPointerType->Name(),pPointerType));
}

MStruct* MTypes_Imp::CreateStruct( MString StructName )
{
// 	MType* retType = GetTypeByName(StructName);
// 	if (retType == NULL)
// 	{
// 		MStruct* pStruct = new MStruct(StructName);
// 		AddType(pStruct);
// 		return pStruct;
// 	}
// 	else
// 	{
// 		throw TypeNameAlreadyExist();
// 	}
	return NULL;
}

bool MTypes_Imp::ImportFrom( MString xmlTypes )
{
	CMarkup XmlPaser;
	XmlPaser.SetDoc(xmlTypes);
	XmlPaser.ResetPos();
	if(XmlPaser.FindElem("types") == false)
		return false;

	XmlPaser.IntoElem();
	while(XmlPaser.FindElem("Array") == true)
	{
		CreateArray(XmlPaser.GetSubDoc(),"test");
	}

	XmlPaser.ResetMainPos();
	while(XmlPaser.FindElem("struct") == true)
	{
		MString structName = XmlPaser.GetAttrib("name");
		CreateStruct(structName);
	}

	XmlPaser.ResetMainPos();
	while(XmlPaser.FindElem("List") == true)
	{
		MString structName = XmlPaser.GetAttrib("name");
		CreateList(structName);
	}


	XmlPaser.ResetMainPos();
	while(XmlPaser.FindElem("struct") == true)
	{
		MString structName = XmlPaser.GetAttrib("name");
		MStruct* pStruct = (MStruct*)this->GetTypeByName(structName);
		pStruct->Import(XmlPaser.GetSubDoc());
	}

	XmlPaser.ResetMainPos();
	while(XmlPaser.FindElem("List") == true)
	{
		MString structName = XmlPaser.GetAttrib("name");
		MList* pList = (MList*)this->GetTypeByName(structName);
		pList->Import(XmlPaser.GetSubDoc());
	}
	return true;
}

void MTypes_Imp::CreateInnerTypes()
{
	AddType(new MDDWORD());
	AddType(new MDWORD());
	AddType(new MWORD());
	AddType(new MBYTE());
	AddType(new MNullType());
	AddType(new MChar());
	AddType(new MWChar());
	AddType(new MFloat());

	AddType(new MStdString());
}

void MTypes_Imp::Reset()
{
	ClearAll();

	CreateInnerTypes();
}

void MTypes_Imp::ClearAll()
{
	TypeContainer_Type::iterator iter = m_TypesContainer.begin();
	for(;iter != m_TypesContainer.end();iter++)
	{
		MType* pType = iter->second;
		delete pType;
	}
	m_TypesContainer.clear();
}
MArray* MTypes_Imp::NewArray( MString memberName, MString subTypeName, int size ) 
{
	MArray* pArray = new MArray(memberName, this->GetTypeByName(subTypeName), size);
	AddType(pArray);
	return pArray;
}


MType* MTypes_Imp::CreateArray( MString xmlArray , MString memberName )
{
	CMarkup XmlPaser;
	XmlPaser.SetDoc(xmlArray);
	XmlPaser.FindElem();

	MString strSize=XmlPaser.GetAttrib("size");
	stringstream ssTemp(strSize);
	int size;
	if(strSize.length()>=3 && strSize[0] == '0' && strSize[1] == 'x')
	{
		ssTemp>>hex>>size;
	}
	else
	{
		ssTemp>>size;
	}
	MString subTypeName = XmlPaser.GetAttrib("type");

	stringstream ss;
	ss<<size;
	
	MArray *mchars = NewArray(subTypeName+"_"+ss.str(), subTypeName, size);

	return mchars;
}

MType* MTypes_Imp::CreateList( MString name )
{
	return NULL;
}


END_MARIONETTE